package com.xxx.system.service.impl;


import com.github.pagehelper.PageHelper;
import com.xxx.system.domain.Role;
import com.xxx.system.mapper.RoleMapper;
import com.xxx.system.query.RoleQuery;
import com.xxx.system.service.IRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
// 查询事务控制方式：设置只读 支持当前事务，如果没有当前事务，就以非事务方法执行。
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class RoleServiceImpl implements IRoleService {
    @Autowired
    private RoleMapper roleMapper;

    @Override
    @Transactional
    public void deteleById(Long id) {
        roleMapper.deteleById(id);
        //删除主表后对中间表进行维护
        handleForMenuByEmpId(id);
        handleForPermissionByEmpId(id);
    }
    //根据RoleId删除中间表数据
    private void handleForPermissionByEmpId(Long id) {
        roleMapper.handleForPermissionByEmpId(id);
    }

    //根据RoleId删除中间表数据
    private void handleForMenuByEmpId(Long id) {
        roleMapper.handleForMenuByEmpId(id);
    }

    @Override
    public Role findOne(Long id) {
        return roleMapper.findOne(id);
    }

    @Override
    public List<Role> findAll() {
        List<Role> list = roleMapper.findAll();//从数据库中查询部门树
        return list;
    }

    @Override
    public List<Role> queryPage(RoleQuery RoleQuery) {
        //开始设置分页信息
        //干了三件事情：
        //1.查询总条数 2.根据驱动名称自动添加分页 3.分页查询返回结果
        PageHelper.startPage(RoleQuery.getCurrentPage(), RoleQuery.getPageSize());
        //直接高级查询，自动实现分页
        List<Role> roleList = roleMapper.queryPage(RoleQuery);
//        for (Role role : roleList) {
//            //查询所有menuid的集合,根据role-id
//            List<Long> list=roleMapper.findAllMenusByRoleId(role);
//            if (list!=null&&list.size()>0){
//                role.setMenus(list);
//            }
//            //查询所有permsid的集合,根据role-id
//            List<Long> list2=roleMapper.findAllPermsByRoleId(role);
//            if (list2!=null&&list2.size()>0){
//                role.setPerms(list2);
//            }
//        }
        //优化上述循环SQL的代码
        //对分页角色集合映射为id集合
        List<Long> roleIds = roleList.stream().map(item -> item.getId()).collect(Collectors.toList());
        //查询菜单id集合,通过roleIds,利用Role中固有menuIds集合属性封装
        List<Role> menuIds=roleMapper.findMenuIdsByRoleIds(roleIds);
        Map<Long, Role> collectMenus = menuIds.stream().collect(Collectors.toMap(Role::getId, role -> role));
        //permission表中同理
        List<Role> permsIds=roleMapper.findPerIdsByRoleIds(roleIds);
        Map<Long, Role> collectPerms = permsIds.stream().collect(Collectors.toMap(Role::getId, role -> role));
        for (Role role : roleList) {
            //对每个Role设置menus的ID集合
            Role role1 = collectMenus.get(role.getId());
            List<Long> menus = role1.getMenus();
            if (menus!=null&&menus.size()>0){
                role.setMenus(menus);
            }
            //perms同理
            Role role2 = collectPerms.get(role.getId());
            List<Long> perms = role2.getPerms();
            if (perms!=null&&perms.size()>0){
                role.setPerms(perms);
            }
        }

        return roleList;
    }

    @Override
    @Transactional
    public void deleteRoleByIds(Long[] ids) {
        roleMapper.deleteRoleByIds(ids);
        //批量删除中间表数据
        deleteRoleByIdsForMenu(ids);
        deleteRoleByIdsForPermission(ids);
    }

    private void deleteRoleByIdsForPermission(Long[] ids) {
        roleMapper.deleteRoleByIdsForPermission(ids);
    }

    private void deleteRoleByIdsForMenu(Long[] ids) {
        roleMapper.deleteRoleByIdsForMenu(ids);
    }

    @Override
    public void addOrUpdate(Role role) {
        if (role.getId()==null){
            //新增
            roleMapper.add(role);
            //对菜单中间表进行维护
            if (role.getMenus()!=null&&role.getMenus().size()!=0){
                //对菜单中间表新增
                handleForMenuIns(role);
            }
            //权限表同理
            if (role.getPerms()!=null&&role.getPerms().size()!=0){
                //对权限中间表新增
                handleForPermissionIns(role);
            }

        }else {
            //修改
            roleMapper.update(role);
            //先删除菜单中间数据,再新增
            //删除
            handleForMenuDel(role);//需要提到外面,防止可能修改后没选
            if (role.getMenus()!=null&&role.getMenus().size()!=0){
                //对菜单中间表新增
                handleForMenuIns(role);
            }
            handleForPermissionDel(role);
            if (role.getPerms()!=null&&role.getPerms().size()!=0){
                //对菜单中间表新增
                handleForPermissionIns(role);
            }
        }
    }

    private void handleForPermissionDel(Role role) {
        roleMapper.delForRelatinPermission(role);
    }

    private void handleForPermissionIns(Role role) {
        roleMapper.insForRelatinPermission(role);
    }

    private void handleForMenuDel(Role role) {
        roleMapper.delForRelatinMenu(role);
    }

    private void handleForMenuIns(Role role) {
        roleMapper.insForRelatinMenu(role);
    }

    //无限极树
    /*1. 一次性查询出所有数据，放到内存中，可以使用map
    2. 从所有数据中找出第一层级/顶级类型：这就是我们需要返回的数据
    3. 遍历所有类型只要不是第一层级的，找自己的上级，并将自己放入上级的children中*/
    /*@Override
    public List<Role> getRoleTree(List<Role> list, Long id) {
        //1.查询所有类型,redis取值
        //2.把所有list转换为map,id为key,自己为value
        Map<Long, Role> roleMap =
                list.stream().collect(
                        Collectors.toMap(Role::getId, (d) -> d)
                );
        //3.定义返回的typeTree集合
        List<Role> typeTree = new ArrayList<Role>();
        //4.找到顶层类型，没有上级类型就是顶级类型
        for (Role role : list) {
            //equals自己的id直接跳过，Long缓存问题，用equals
            if (role.getId().equals(id)) continue;
            if (role.getParentId() == null) {
                typeTree.add(role);
            } else {//非顶级类型加入到父级类型下
                //找到父类型
                Role parentRole = roleMap.get(role.getParentId());
                //添加自己到父类型的子类型集合中
                parentRole.getChildren().add(role);
            }
        }
        return typeTree;
    }*/
}